package concurrecy.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

class Horse implements Runnable {
    private static int count = 0;
    private final int id = count ++;
    private int strides = 0;
    private Random random = new Random();

    private CyclicBarrier barrier;

    public Horse(CyclicBarrier barrier) {
        this.barrier = barrier;
    }

    @Override
    public String toString() {
        return "Horse" + id;
    }

    public int getStrides() {
        return strides;
    }

    public void print() {
        StringBuilder sb = new StringBuilder();
        sb.append(this);
        sb.append(" : ");
        for (int i = 0; i < strides; i++) {
            sb.append("=");
        }
        sb.append(">");
        System.out.println(sb.toString());
    }

    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                strides += random.nextInt(3);
                System.out.println(this + " await");
                barrier.await();
            }
            System.out.println(this + " exit");
        } catch(InterruptedException | BrokenBarrierException e) {
            System.out.println(this + " interrupted");
        }
    }
}

public class HorseRace {
    // 马的个数
    final static int HORSE_NUM = 7;
    // 帧频
    final static int FPS = 24;
    // 赛道长度
    final static int LENGTH_ROAD = 100;

    public static void main(String[] args) {
        final ExecutorService service = Executors.newCachedThreadPool();
        final List<Horse> horses = new ArrayList<>();
        final int sleep_time = 1000 / FPS;
        CyclicBarrier barrier = new CyclicBarrier(HORSE_NUM, () -> {
            List<Horse> winners = new ArrayList<>();
            for (Horse horse : horses) {
                horse.print();
                if(horse.getStrides() >= LENGTH_ROAD) {
                    winners.add(horse);
                }
            }
            if(!winners.isEmpty()) {
                Horse winner = winners.get(0);
                if(winners.size() > 1) {
                    for (int i = 1; i < winners.size(); i++) {
                        Horse t = winners.get(i);
                        if(t.getStrides() > winner.getStrides())
                            winner = t;
                    }
                }
                System.out.println("Winner is " + winner);
                service.shutdownNow();
                System.exit(0);
            }
            try {
                TimeUnit.MILLISECONDS.sleep(sleep_time);
            } catch (InterruptedException e) {
                System.out.println("barrier interrupted");
            }
        });
        for (int i = 0; i < HORSE_NUM; i++) {
            Horse horse = new Horse(barrier);
            service.execute(horse);
            horses.add(horse);
        }
    }
}
